#pragma once
#include"nocopy.hpp"
#include<iostream>
#include<string>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include"Log.hpp"
#include"InetAddr.hpp"

static const int gsocketfd=-1;
static const uint16_t glocalport=8888;
enum
{
    SOCKET_ERROR=1,
    BIND_ERROR
};
class UdpServer:public nocopy//继承nocopy取消拷构造
{
public:
    UdpServer(uint16_t port=glocalport):
    _socketfd(gsocketfd),
    _localport(port),
    _isrunning(false)
    {}
    void InitServer()
    {
        _socketfd=::socket(AF_INET,SOCK_DGRAM,0);
        if(_socketfd<0)
        {
            LOG(FATAL,"socket,error\n");
            exit(SOCKET_ERROR);
        }
        LOG(DEBUG,"socket create success socket:%d\n",_socketfd);
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(_localport);
        //local.sin_addr.s_addr = inet_addr(_localip.c_str());
        local.sin_addr.s_addr=INADDR_ANY;
        int b=bind(_socketfd,(struct sockaddr*)&local,sizeof(local));
        if(b<0)
        {
            LOG(FATAL,"bind error\n");
            exit(BIND_ERROR);
        }
        LOG(DEBUG,"bind success \n");
    }
    void Start()
    {
        _isrunning=true;
        char inbuff[1024];
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            ssize_t n=recvfrom(_socketfd,inbuff,sizeof(inbuff)-1,0,(struct sockaddr*)&peer,&len);
            if(n>0)
            {
                // uint16_t peerport=ntohs(peer.sin_port);
                // std::string peerip=inet_ntoa(peer.sin_addr);
                InetAddr addr(peer);

                inbuff[n]='\0';
                // std::cout<<"[ "<<peerip<<" : "<<peerport<<" ] :"<<inbuff<<std::endl;
                std::cout<<"[ "<<addr.Ip()<<" : "<<addr.Port()<<" ] :"<<inbuff<<std::endl;

                std::string echo_string="[udp_server_echo]:";
                echo_string+=inbuff;
                sendto(_socketfd,echo_string.c_str(),echo_string.size(),0,(struct sockaddr*)&peer,len);

            }
        }
    }
    ~UdpServer()
    {
        if(_socketfd>-1)
        {
            ::close(_socketfd);
        }
    }
private:
    int _socketfd;
    uint16_t _localport;
    //std::string _localip;
    bool _isrunning;
};